using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using outlook = Microsoft.Office.Interop.Outlook;
using System.Reflection;

namespace ESnatch
{
    public delegate void ReportStatus(string status, int nCount);

    public class XMLDump
    {
        StreamWriter m_writer;
        ReportStatus m_reportTo;
        bool m_bInterrupt;

        public XMLDump(string outputPath, ReportStatus callback)
        {
            FileStream fs = new FileStream(outputPath, FileMode.Create, FileAccess.Write);
            m_writer = new StreamWriter(fs, Encoding.UTF8);
            m_reportTo = callback;
        }

        public void Close()
        {
            m_writer.Flush();
            m_writer.Close();
        }

        public void suspend()
        {
            m_bInterrupt = true;
        }

        public void writeMailBox(outlook.MAPIFolder folder, List<OutputMapping> mappings)
        {
            if (m_reportTo != null)
                m_reportTo("Records written", 0);
            m_writer.WriteLine("<?xml version=\"1.0\" ?>");
            m_writer.WriteLine(ToOpenTag(folder.Name));
            int x = 0;
            int ignored = 0;
            m_bInterrupt = false;

            foreach(object oItem in folder.Items)
            {
                outlook.MailItem mailItem = null;
                try
                {
                    mailItem = (outlook.MailItem)oItem;
                }
                catch (Exception e)
                {
                    // Ignore this one;
                    ignored++;
                }
                if (mailItem != null)
                {
                    m_writer.WriteLine(ToOpenTag("item"));
                    writeItem(mailItem, mappings);
                    m_writer.WriteLine(ToCloseTag("item"));
                    x++;
                    if (m_reportTo != null)
                        m_reportTo("Records written", x);
                }
            }
            m_writer.WriteLine(ToCloseTag(folder.Name));
            string finalMsg = "Export complete.  Records ignored " +
                Convert.ToString(ignored) + ", records written:";
            if (m_reportTo != null)
                m_reportTo(finalMsg, x);
        }

        protected void writeItem(outlook.MailItem mailItem, List<OutputMapping> mappings)
        {
            foreach (OutputMapping mapping in mappings)
            {
                //cmd.Parameters.Refresh();
                if (mapping.Include)
                {
                    String propname = mapping.SrcPropInfo.Name;
                    Object propVal = mailItem.GetType().InvokeMember(propname,
                                    BindingFlags.GetProperty, null, mailItem, null);

                    String sOut = ToOpenTag(propname) + ToCData(propVal) + ToCloseTag(propname);
                    m_writer.WriteLine(sOut);
                }
            }
        }

        protected string ToCData(object value)
        {
            string sVal = Convert.ToString(value);
            string result = "<![CDATA[" + sVal + "]]>";
            return result;
        }

        protected string ToOpenTag(string name)
        {
            return "<" + ToTagName(name) + ">";
        }

        protected string ToCloseTag(string name)
        {
            return "</" + ToTagName(name) + ">";
        }

        protected string ToTagName(string value)
        {
            string result = value.Replace(" ", "_");
            return result;
        }
    }
}
